nnotifd NSDistNotifで制御するObj-C製CL実行デーモンみたいなの


概要

コマンドラインから起動して、Mac内を駆け巡るNSDistributedNotificationを受信、

特定の形式だった場合、コマンドラインを実行するプログラムを作った。

Macアプリではなく、Macコマンドラインアプリ。


nnotifdというコマンド名にした。

https://github.com/sassembla/nnotifd


スクリーンショット 2013-05-01 22.24.17.png


SocketRoundabout

(WebSocketP、BT、HTTP、NSDistNotif、他、通信プロトコルを相互接続するツール)

と組み合わせて使う。


単体でも使い道があるとは思うが、わざわざそのために脳みそ使って考える必要も無いだろう。



動機

どんなニーズがこれを作らせたか、というと、

・Mac環境、サーバサイドで動く、コマンドライン実行クライアントが欲しかった

→SocketRoundaboutがその機能を持ちたくないので、コマンドラインを外部で動かすもの、という位置づけのプロダクトが必要だった。


・コマンドライン実行自体を、NSDistributedNotificationをトリガーとして行いたかった

完全にSocketRoundaboutが話せるプロトコルだった、という都合。

→そういえば大昔につくったObj-Cサーバあったよね!

ということで、改造していろんな機能オミットしまくって、こうなった。


ちなみにデーモンって言ってるけどまだぜんぜんデーモンじゃない。


形式

会社でつかってる独自形式(文字列+JSON)をベースに、適当にコピーした形式を使っている。

SublimeSocketとほぼ同系統だけど、こっちのほうが機能が圧倒的に少ない。必要ないしな。


全体

nn:[JSONARRAY]


ヘッダ

nn:

パラメータ

[JSONARRAY]


という形の文字列を送り込むと、コマンドラインとパラメータとパイプを解釈して、コマンドラインとして実行される。



例's

始動

nnotifd -c start -i IDENTITY


で、アイデンティティ = nnotifdが受信するチャンネル、という風に設定して起動できる。

別に起動と同時にスタートしないでもいいんだけど、-iでの「受信するアイデンティティの決定」だけは必須。


nnotifdとのコミュニケーションには、NSDistributedNotificationを生成すればOKで、

これはキーとかが合ってればプロセス間を跨ぎ放題、なんでも送ってOKというゆっるーい感じになっている。


実行順は発行順と同じにならない(順保証がされない)ので、使いたい部分だけ注意して作った。

実際には準保証をするための仕掛けもNSなんちゃらには用意されているが、テストしづらかったので、これから順保証モードとして着手する。


なんかNSDistNotif越しの実行がしたい場合、

nnotifdを起動したあと、


付属のnnotif(入力した文字列をNSDistNotifにして発行するツール)で送付するか、どっかObj-Cで書いて送り込む。

nnotif -t IDENTITY -k NN_DEFAULT_ROUTE -i nn@ -kill

これでkillできる。

-iはnnotifのオプションで、input。 nn@以降の文字をnnotifdに対するコマンドとしてIDENTITYに対して送り込む。


Obj-Cで書く場合、

[[NSDistributedNotificationCenter defaultCenter] postNotificationName:IDENTITY object:nil userInfo:dict deliverImmediately:YES];


で良いと思う。dictの中身はパラメータになる。

コレに関しては、nnotifが | を受けられるため、コマンドラインから使えるほうが万倍いろんなことができる。



nnotifdで特定のコマンドラインを実行したい場合、

nnotif -t IDENTITY -k NN_DEFAULT_ROUTE -i nn@ -e nn:["/bin/pwd"]


とかで、pwdが実行できる。

nn@ までが入力のためのヘッダ、-eから先がnntoifdで実行されるコマンドの独自形式JSONArray。


pwdがフルパスになってるのは、これの内部実装がNSTaskを使用しているので、コマンドのありかのパスを総て書かないと動かないため。


nnotifd内で使用したいコマンドに対してパイプを使う事もできて、

nnotif -t IDENTITY -k NN_DEFAULT_ROUTE -i nn@ -e nn:["/bin/cat","/SOMEWHERE/SOMETHING.txt","|","/usr/bin/grep","-e","KEYWORD"]


とかで、

/SOMEWHERE/SOMETHING.txt に対してgrep KEYWORD を実行する、みたいなのができる。



おまけで、nnotif自体がパイプを扱えるので、

tail -f /SOMEWHERE/SOMETHING.log | nnotif -t IDENTITY -k NN_DEFAULT_ROUTE

とかで、tail結果をダイレクトに、連続した状態でどこかへと送り込める。

もちろんnnotifdのなかでnnotifを使用して別のNSDistNotifを発生させることもできる。


これで、例えばサーバからのメッセージを受けて特定のコマンドラインを実行したり、

実行した内容を同種の通信手段を使っているSocketのおばけみたいなプロダクトに送り込んだりできる。



具体的な用途

特定のコマンドラインを実行し、その結果を、nnotifなどを使い、NSDistNotifで送り出す。

NSDistNotification -> BT とか、

NSDistNotification -> WebSocket とか、そういう転送ができるツールがあるので、

そのツール自体のコントロールとか、プッシュの「起点」に使用する。


そうっとう異様なニーズに応える代物。


組み合わせで、WebSocketClientをサーバサイドでnodeとかより安定した挙動できるように動かそう、みたいな

ニーズに応えるために作った。

ぶっちゃけnodeの難解なコントロールに耐えられなかった人間が狂気で作った何かのためのパーツ。